package com.ashraya.framework.dao;

import java.io.Serializable;
import java.util.Collection;

import org.hibernate.FetchMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;

/**
 * 
 * Core Criteria Object
 * <p>
 * Created on Feb 28, 2010
 * <p>
 * 
 * @author PankajK
 * 
 */
public class CoreCriteria<T> implements Serializable {

	private static final long serialVersionUID = 1274405465865851859L;
	public final static MatchMode ANY = MatchMode.ANYWHERE;
	public final static MatchMode END = MatchMode.END;
	public final static MatchMode BEGIN = MatchMode.START;
	private int fetchSize;

	/**
	 * @return Returns the fetchSize.
	 */
	public int getFetchSize() {
		return fetchSize;
	}

	/**
	 * @param fetchSize
	 *            The fetchSize to set.
	 */
	public void setFetchSize(int fetchSize) {
		this.fetchSize = fetchSize;
	}

	protected DetachedCriteria criteria = null;

	/**
	 * Constructor
	 */
	public CoreCriteria(Class<T> clazz) {
		super();
		criteria = DetachedCriteria.forClass(clazz);

	}

	/**
	 * Constructor
	 */
	public CoreCriteria(Class<T> clazz, String alias) {
		super();
		criteria = DetachedCriteria.forClass(clazz, alias);
	}

	/**
	 * Create an alias
	 * 
	 * @param aliasField
	 * @param aliasValue
	 */
	public void alias(String aliasField, String aliasValue) {
		criteria.createAlias(aliasField, aliasValue);
	}

	/**
	 * Create like criteria
	 * 
	 * @param likeField
	 * @param likeValue
	 * @param mode
	 */
	public void like(String likeField, String likeValue, MatchMode mode) {
		criteria.add(Restrictions.like(likeField, likeValue, mode));
	}

	/**
	 * Create equals criteria
	 * 
	 * @param equalField
	 * @param equalValue
	 */
	public void equal(String equalField, Object equalValue) {
		criteria.add(Restrictions.eq(equalField, equalValue));
	}

	/**
	 * Criteria not equal
	 * 
	 * @param notEqualField
	 * @param notEqualValue
	 */
	public void notEqual(String notEqualField, Object notEqualValue) {
		criteria.add(Restrictions.ne(notEqualField, notEqualValue));
	}

	/**
	 * Greater than criteria
	 * 
	 * @param gField
	 * @param gValue
	 */
	public void greater(String gField, Object gValue) {
		criteria.add(Restrictions.gt(gField, gField));
	}

	/**
	 * Less than criteria
	 * 
	 * @param ltField
	 * @param ltValue
	 */
	public void less(String ltField, Object ltValue) {
		criteria.add(Restrictions.lt(ltField, ltValue));
	}

	/**
	 * Greater or Equal
	 * 
	 * @param geField
	 * @param geValue
	 */
	public void greaterEqual(String geField, Object geValue) {
		criteria.add(Restrictions.ge(geField, geValue));
	}

	/**
	 * The field is either Greater or Equal to given value OR Null
	 * 
	 * @param genField
	 * @param genValue
	 */
	public void greaterEqualNull(String genField, Object genValue) {
		criteria.add(Restrictions.or(Restrictions.ge(genField, genValue), Restrictions.isNull(genField)));
	}

	/**
	 * The field is either Greater to given value OR Null
	 * 
	 * @param genField
	 * @param genValue
	 */
	public void greaterNull(String genField, Object genValue) {
		criteria.add(Restrictions.or(Restrictions.gt(genField, genValue), Restrictions.isNull(genField)));
	}

	/**
	 * The field is either Equal to given value OR Null
	 * 
	 * @param genField
	 * @param genValue
	 */
	public void equalNull(String genField, Object genValue) {
		criteria.add(Restrictions.or(Restrictions.eq(genField, genValue), Restrictions.isNull(genField)));
	}

	/**
	 * Less or equal
	 * 
	 * @param leField
	 * @param leValue
	 */
	public void lessEqual(String leField, Object leValue) {
		criteria.add(Restrictions.le(leField, leValue));
	}

	/**
	 * Order the list by given field name in ascending order
	 * 
	 * @param fieldName
	 */
	public void orderAscend(String fieldName) {
		criteria.addOrder(Order.asc(fieldName));
	}

	/**
	 * Order the list by given field name in descending order
	 * 
	 * @param fieldName
	 */
	public void orderDescend(String fieldName) {
		criteria.addOrder(Order.desc(fieldName));
	}

	/**
	 * Fetch objects in EAGER mode
	 * 
	 * @param fieldName
	 */
	public void fetchEager(String fieldName) {
		criteria.setFetchMode(fieldName, FetchMode.JOIN);
	}

	/**
	 * Return all that belong to a collection
	 * 
	 * @param inField
	 * @param inCollection
	 */
	public void in(String inField, Collection<T> inCollection) {
		criteria.add(Restrictions.in(inField, inCollection));
	}

	/**
	 * @return Returns the criteria.
	 */
	public DetachedCriteria getCriteria() {
		return criteria;
	}

	/**
	 * @return Returns the criteria.
	 */
	public void isNull(String fieldName) {
		criteria.add(Restrictions.isNull(fieldName));
	}

	public void notNull(String fieldName) {
		criteria.add(Restrictions.isNotNull(fieldName));
	}

	public void exists(DetachedCriteria subquery) {
		criteria.add(Subqueries.exists(subquery));
	}

	public void equalIfNotNull(String field, Object value) {
		if (value != null) {
			equal(field, value);
		}
	}

}
